package com.csun.cmny.provider.device.csun.gateway;

import com.csun.cmny.mqtt.constant.MqttMsgConstants;
import com.csun.cmny.mqtt.entity.*;
import com.csun.cmny.provider.controller.websocket.WebSocketUtils;
import com.csun.cmny.provider.dao.DmcCsunGatewayCmdHiMapper;
import com.csun.cmny.provider.dao.DmcCsunGatewayCmdMapper;
import com.csun.cmny.provider.device.csun.gateway.entity.CsunGatewayData;
import com.csun.cmny.provider.device.csun.sleep.SleepMessageHandler;
import com.csun.cmny.provider.model.constant.*;
import com.csun.cmny.provider.model.domain.*;
import com.csun.cmny.provider.model.dto.alert.DeviceAlertPageQuery;
import com.csun.cmny.provider.model.dto.button.CsunButtonPageQuery;
import com.csun.cmny.provider.model.dto.device.DeviceStatus;
import com.csun.cmny.provider.model.enums.device.DeviceStatusEnum;
import com.csun.cmny.provider.model.enums.device.DmcDeviceTypeEnum;
import com.csun.cmny.provider.model.vo.OldmanBedRoomBuildingVo;
import com.csun.cmny.provider.model.vo.csunbody.BodyGroupVo;
import com.csun.cmny.provider.model.vo.csunbody.DmcCsunBodySensorVo;
import com.csun.cmny.provider.model.vo.csunbutton.DmcCsunButtonVo;
import com.csun.cmny.provider.model.vo.device.DmcDeviceAlertVo;
import com.csun.cmny.provider.service.*;
import com.csun.cmny.provider.utils.DateUtil;
import com.csun.cmny.provider.utils.DeviceLogUtils;
import com.csun.cmny.provider.utils.MqttMessageUtils;
import com.csun.cmny.util.PublicUtil;
import com.csun.cmny.util.RedisKeyUtil;
import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2019-03-05 17:48
 * @Description: gateway message handler
 */
@Slf4j
public class GatewayMessageHandler implements MessageHandler {

    Gson gson = new Gson();

    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private DmcDeviceAlertService dmcDeviceAlertService;
    @Resource
    private DmcGatewayDataService dmcGatewayDataService;
    @Resource
    private DmcGatewayDataHiService dmcGatewayDataHiService;
    @Resource
    private DmcDeviceLogService dmcDeviceLogService;
    @Resource
    private DmcDeviceService dmcDeviceService;
    @Resource
    private DmcCsunBodySensorLocationService dmcCsunBodySensorLocationService;
    @Resource
    private DmcCsunBodySensorConfigService dmcCsunBodySensorConfigService;
    @Resource
    private DmcCsunHumidistatDataService dmcCsunHumidistatDataService;
    @Resource
    private DmcCsunHumidistatDataHiService dmcCsunHumidistatDataHiService;
    @Resource
    private DmcCsunHumidistatLocationService dmcCsunHumidistatLocationService;
    @Resource
    private DmcCsunHumidistatThresholdService dmcCsunHumidistatThresholdService;
    @Resource
    private GatewayMessageSender gatewayMessageSender;
    @Resource
    private CsunGatewayMessageGateway csunGatewayMessageGateway;
    @Resource
    private DmcCsunGatewayCmdMapper dmcCsunGatewayCmdMapper;
    @Resource
    private DmcCsunGatewayCmdHiMapper dmcCsunGatewayCmdHiMapper;
    @Resource
    private DmcCsunGatewayConfigHumidistatService dmcCsunGatewayConfigHumidistatService;
    @Resource
    private DmcCsunGatewayBindService dmcCsunGatewayBindService;
    @Resource
    private DmcCsunHumidistatConfigService dmcCsunHumidistatConfigService;
    @Resource
    private DmcDeviceOnlineRecordService dmcDeviceOnlineRecordService;
    @Resource
    private WebSocketUtils webSocketUtils;
    @Resource
    private DmcCsunVersionSetDeviceService dmcCsunVersionSetDeviceService;
    @Resource
    private DeviceLogUtils deviceLogUtils;
    @Resource
    private DmcLifeTransducerRoomConfigService dmcLifeTransducerRoomConfigService;
    @Resource
    private DmcLifeTransducerDefaultConfigService lifeTransducerDefaultConfigService;
    @Resource
    private DmcCsunBodyGroupBindService dmcCsunBodyGroupBindService;
    @Resource
    private DmcCsunBodyGroupService dmcCsunBodyGroupService;
    @Resource
    private DmcCsunButtonLocationService dmcCsunButtonLocationServiceImpl;

    /**
     * 处理sub client接收到的消息
     *
     * @param message
     * @throws MessagingException
     */
    @Override
    public void handleMessage(Message<?> message) throws MessagingException {

        String msg = message.getPayload().toString();

        log.info("gateway message topic = {}", message.getHeaders().get("mqtt_receivedTopic"));
        log.info("gateway message qos = {}", message.getHeaders().get("mqtt_receivedQos"));
        log.info("gateway message = {}", msg);

        try {
            new JsonParser().parse(msg);
        } catch (JsonParseException e) {
            log.error("bad json: {} " + msg);
            return;
        }

        String msgType = MqttMessageUtils.getMsgType(msg);
        if (PublicUtil.isEmpty(msgType)) {
            log.error("no msg type");
            return;
        }



        switch (msgType) {
            case MqttMsgConstants.INVITE_HEAT:         // 处理网关心跳数据
                dealGatewayHeat(msg);
                break;
            case MqttMsgConstants.INVITE_CLOSE:        // 处理网关掉线数据
                dealGatewayClose(msg);
                break;
            case MqttMsgConstants.GATAWAY_BTN_MSG:     // 处理紧急按钮消息
                dealGatewayButtonMsg(msg);
                break;
            case MqttMsgConstants.GATEWAY_BODY_MSG:    // 处理人感报警消息
                dealGatewayBodySensorMsg(msg);
                break;
            case MqttMsgConstants.GATEWAY_BODY_SENSOR_TOUCH:    // 处理人感触发消息
                dealGatewayBodyTouchMsg(msg);
                break;
            case MqttMsgConstants.GATEWAY_BODY_ADC_MSG:    // 处理人感电量消息
                dealGatewayBodySensorAdcMsg(msg);
                break;
            case MqttMsgConstants.GATEWAY_BODY_SENSOR_SET_TIME_ACK_MSG:     // 处理LIFE人感时间设置确认消息数据
                dealGatewayBodySensorSetTimeAckMsg(msg);
                break;
            case MqttMsgConstants.GATEWAY_BODY_SENSOR_INVITE_HEAT:         //处理人感心跳
                dealGatewayBodySensorInviteHeat(msg);
                break;
            case MqttMsgConstants.GATEWAY_BODY_SENSOR_HOME_MSG:        //检测厕所是否有人 in 在厕所，out，不在厕所
                dealGatewayBodysenorHomeMsg(msg);
                break;
            case MqttMsgConstants.LOG_MSG:             // 处理设备log消息
                dealLogMsg(msg);
                break;
            case MqttMsgConstants.GATEWAY_HUMIDISTAT_MSG:
                dealGatewayHumidistatMsg(msg);          // 处理温湿度传感器数据
                break;
            case MqttMsgConstants.GATEWAY_HUMIDISTAT_BIND_ACK_MSG:     // 处理温湿度传感器绑定确认消息数据
                dealGatewayHumidistatBindAckMsg(msg);
                break;
            case MqttMsgConstants.GATEWAY_BODY_SENSOR_BIND_ACK_MSG:     // 处理温湿度传感器绑定确认消息数据
                dealGatewayBodySensorBindAckMsg(msg);
                break;
            case MqttMsgConstants.GATEWAY_BUTTON_BIND_ACK_MSG:     // 处理温湿度传感器绑定确认消息数据
                dealGatewayButtonBindAckMsg(msg);
                break;
            case MqttMsgConstants.GATEWAY_HUMIDISTAT_SET_TIME_ACK_MSG:     // 处理温湿度传感器时间设置确认消息数据
                dealGatewayHumidistatSetTimeAckMsg(msg);
                break;
            case MqttMsgConstants.MQTT_VERSION_UPDATE_ACK_MSG : // 版本升级确认消息
                dealVerUpdateAckMsg(msg);
                break;
            case MqttMsgConstants.MQTT_UPDATE_STATUS_MSG :  // 版本升级状态消息
                dealUpdateStatusMsg(msg);
                break;
            case MqttMsgConstants.MQTT_DOOR_MSG :  // 门磁消息
                dealDoorMsg(msg);
                break;
            default:
                log.error("unknown msg type = {}", msgType);
                break;
        }
    }

    /**
     * 处理收到版本升级状态指令
     *
     * @param msg
     */
    private void dealUpdateStatusMsg(String msg) {

        MsgUpdateStatus msgUpdateStatus = gson.fromJson(msg, MsgUpdateStatus.class);

        int stat = DeviceConstant.VERSION_SET_CMD_FAILED;

        if ("1".equals(msgUpdateStatus.getStatus())) {
            stat = DeviceConstant.VERSION_SET_CMD_SUCCESS;
        } else if ("-1".equals(msgUpdateStatus.getStatus())){
            stat = DeviceConstant.VERSION_SET_CMD_DOWN;
        }

        dmcCsunVersionSetDeviceService.updateByTaskId(msgUpdateStatus.getUpdateEventId(), stat);

        // TODO 暂时不回复ack
    }

    /**
     * 处理收到版本升级指令
     *
     * @param msg
     */
    private void dealVerUpdateAckMsg(String msg) {

        MsgUpdateVerAck msgUpdateVerAck = gson.fromJson(msg, MsgUpdateVerAck.class);

        dealGatewayMsgOk(MqttMsgConstants.MQTT_VERSION_UPDATE_MSG, msgUpdateVerAck.getEventId(),
                msgUpdateVerAck.getSn());

        dmcCsunVersionSetDeviceService.updateByTaskId(msgUpdateVerAck.getEventId(), DeviceConstant.VERSION_SET_CMD_SEND);
    }

    private void dealGatewayBodySensorInviteHeat(String msg) {

        MsgBodySensorInviteHeat msgBodySensorInviteHeat = gson.fromJson(msg, MsgBodySensorInviteHeat.class);

        String gatewayNo = msgBodySensorInviteHeat.getSn();
        String deviceNo = msgBodySensorInviteHeat.getBodySensorId();

        CsunGatewayData csunGatewayData = (CsunGatewayData) redisTemplate.opsForValue()
                .get(RedisKeyUtil.getCsunGatewayKey(gatewayNo));

        if (PublicUtil.isNotEmpty(csunGatewayData)) {

            /**
             * 设置在线过期时间
             */
            refreshGatewayOnline(csunGatewayData);

            /*
             * 刷新人感离线时间
             * */
            refreshBodySensorOnline(deviceNo);

        } else {
            log.error("csun gateway [{}] not load... ", gatewayNo);
        }

    }

    //刷新人感离线key
    private void refreshBodySensorOnline(String deviceNo) {

        /**
         * @date    2020-03-26
         * @author  chisj
         * @desc    人感绑定房间后才上线
         */
        DmcDevice dmcDevice = dmcDeviceService.queryDeviceByNumber(deviceNo);
        if (PublicUtil.isEmpty(dmcDevice)) {
            log.warn("====> the body sensor [{}] not exist.", deviceNo);
            return;
        }
        DmcCsunBodySensorLocation record = dmcCsunBodySensorLocationService.selectByKey(dmcDevice.getId());
        if (PublicUtil.isEmpty(record)) {
            log.warn("====> the body sensor [{}] not bind.", deviceNo);
            return;
        } else {
            log.info("====> the body sensor [{}] bind.", deviceNo);
        }

        String redisKey = RedisKeyUtil.getCsunBodySensorOnline(deviceNo);

        /**
         * @data    2020-03-19
         * @author  chisj
         * @desc    修复人感频繁在线记录
         */
        DmcDevice deviceNoQuery = (DmcDevice) redisTemplate.opsForValue().get(redisKey);
        if (PublicUtil.isEmpty(deviceNoQuery)) {    // 设备还未离线
            dmcDeviceOnlineRecordService.insertRecordByDeviceNo(deviceNo, OnlineConstant.ON_LINE);
        }

        redisTemplate.opsForValue().set(redisKey, dmcDevice, BodySensorConstant.BODYSENSOR_OFFLINE_TIME, TimeUnit.SECONDS);
        if (!SleepMessageHandler.expireRedisKeySet.contains(redisKey))
            SleepMessageHandler.expireRedisKeySet.add(redisKey);
    }

    private void dealGatewayBodysenorHomeMsg(String msg) {

        MsgBodysenorHome msgBodysenorHome = gson.fromJson(msg, MsgBodysenorHome.class);
        String sn = msgBodysenorHome.getNetgateId();
        String redisKey = RedisKeyUtil.getCsunGatewayKey(sn);

        CsunGatewayData csunGatewayData = (CsunGatewayData) redisTemplate.opsForValue()
                .get(redisKey);

        if (PublicUtil.isNotEmpty(csunGatewayData)) {

            /**
             * 设置在线过期时间
             */
            refreshGatewayOnline(csunGatewayData);

            /*
            * 刷新人感在线时间
            * */
            /**
             * @date    2020-08-30
             * @author  chisj
             * @desc    修复红外人感离线报警
             */
//            refreshBodySensorOnline(msgBodysenorHome.getBodySensorId());

            //查询绑定方式 是否为life绑定
            DmcCsunBodySensorVo vo = dmcCsunBodySensorLocationService.getCsunBodySensorByDeviceNo(msgBodysenorHome.getBodySensorId());
            //校验设备是否绑定
            if (vo == null) {
                log.info("device is not bound = {} ", msgBodysenorHome.getBodySensorId());
                return;
            }
            //校验是否是Life绑定
            if (vo.getBindType() != null && vo.getBindType() != (DeviceConstant.DEVICE_BIND_TYPE_LIFE)) {
                return;
            }

            //将在离房状态 存入reids
            String inRoomKey = RedisKeyUtil.getCsunBodySensorIsInRoomKey(msgBodysenorHome.getBodySensorId());

            //如果由在房变为离房
            if (msgBodysenorHome.getHomeMsg().equals(LifeConstant.OUT_ROOM_STATUS)) {
                //如果不在房中 查询其他设备的判定结果
//                dmcDeviceAlertService.checkOldmanInRoomAndAlert(vo.getRoomId(), vo.getGroupId(), DmcDeviceTypeEnum.CSUN_BODY_SENSOR.getIndex());
                DmcDeviceAlert dmcDeviceAlert = new DmcDeviceAlert();
                OldmanBedRoomBuildingVo obrvo = new OldmanBedRoomBuildingVo();
                /**
                 * @date    2020-04-23
                 * @author  chisj
                 * @desc    使用新人感判断是否在房 - 单人感
                 */
                int i = dmcDeviceAlertService.checkOldmanInRoomAndAlert(vo.getRoomId(), vo.getGroupId(), DmcDeviceTypeEnum.NEWBODY.getIndex(), dmcDeviceAlert, obrvo);
                if(i > 0){
                    dmcDeviceAlertService.sendDeviceAlertMsg(dmcDeviceAlert,obrvo);
                    dmcDeviceAlertService.sendLifeMsg(dmcDeviceAlert, obrvo, LifeConstant.YES_SOUND);
                }
            }

            // 推送设备状态改变消息
            DeviceStatus deviceStatus = new DeviceStatus();
            deviceStatus.setDeviceId(vo.getId());
            deviceStatus.setGroupId(vo.getGroupId());
            deviceStatus.setDeviceNo(vo.getDeviceNo());
            deviceStatus.setMessage(String.format("设备%s检测到老人在离房状态", vo.getDeviceNo()));
            webSocketUtils.pushWebsocketMessageWithStatus(deviceStatus);

            redisTemplate.opsForValue().set(inRoomKey, msgBodysenorHome);
        } else {
            log.error("csun gateway [{}] not load... ", sn);
        }
    }

    private void dealGatewayButtonBindAckMsg(String msg) {

        MsgButtonBindAck msgButtonBindAck = gson.fromJson(msg, MsgButtonBindAck.class);

        dealGatewayMsgOk(MqttMsgConstants.GATEWAY_BUTTON_BIND_MSG, msgButtonBindAck.getEventId(),
                msgButtonBindAck.getNetgateId());
    }

    private void dealGatewayHumidistatBindAckMsg(String msg) {

        MsgHumidistatBindAck msgHumidistatBindAck = gson.fromJson(msg, MsgHumidistatBindAck.class);

        dealGatewayMsgOk(MqttMsgConstants.GATEWAY_HUMIDISTAT_BIND_MSG, msgHumidistatBindAck.getEventId(),
                msgHumidistatBindAck.getNetgateId());
    }

    private void dealGatewayBodySensorBindAckMsg(String msg) {

        MsgBodySensorBindAck msgBodySensorBindAck = gson.fromJson(msg, MsgBodySensorBindAck.class);

        dealGatewayMsgOk(MqttMsgConstants.GATEWAY_BODY_SENSOR_BIND_MSG, msgBodySensorBindAck.getEventId(),
                msgBodySensorBindAck.getNetgateId());
    }

    private void dealGatewayBodySensorSetTimeAckMsg(String msg) {
        MsgBodySensorTimerAck msgBodySensorTimerAck = gson.fromJson(msg, MsgBodySensorTimerAck.class);

        //查询绑定房间
//        DmcCsunBodySensorLocation dmcCsunBodySensorLocation = dmcCsunBodySensorLocationService.selectByKey(Long.valueOf(msgBodySensorTimerAck.getBodySensorId()));
//        if(dmcCsunBodySensorLocation == null){
//            throw new DmcBizException(ErrorCodeEnum.DMC100615001);
//        }

        //
        dealGatewayMsgOk(MqttMsgConstants.GATEWAY_BODY_SENSOR_SET_TIME_MSG, msgBodySensorTimerAck.getEventId(),
                msgBodySensorTimerAck.getBodySensorId());
        //查询房间配置
//        DmcLifeTransducerConfig configQuery = new DmcLifeTransducerConfig();
//        configQuery.setLifeRoomId(dmcCsunBodySensorLocation.getRoomId().longValue());
//        configQuery = dmcLifeTransducerConfigService.selectOne(configQuery);
//
//        //
//        if(!configQuery.getToiletAttentionTime().equals(msgBodySensorTimerAck.getTimeOne()) || !configQuery.getToiletUnusualTime().equals(msgBodySensorTimerAck.getTimeTwo()) || !configQuery.getToiletWarningTime().equals(msgBodySensorTimerAck.getTimeThree())){
//            gatewayMessageSender.setLifeBodySensorTimer(msgBodySensorTimerAck.getNetgateId(),msgBodySensorTimerAck.getBodySensorId(),msgBodySensorTimerAck.getTimeOne(),msgBodySensorTimerAck.getTimeTwo(),msgBodySensorTimerAck.getTimeThree());
//        }
    }

    private void dealGatewayMsgOk(String msgType, String eventId, String sensorNo) {

        DmcCsunGatewayCmd dmcCsunGatewayCmd = new DmcCsunGatewayCmd();
        dmcCsunGatewayCmd.setEventId(eventId);
        dmcCsunGatewayCmd.setMsgType(msgType);
        dmcCsunGatewayCmd.setSensorNo(sensorNo);
        dmcCsunGatewayCmdMapper.delete(dmcCsunGatewayCmd);

        DmcCsunGatewayCmdHi dmcCsunGatewayCmdHi = new DmcCsunGatewayCmdHi();
        dmcCsunGatewayCmdHi.setMsgType(msgType);
        dmcCsunGatewayCmdHi.setEventId(eventId);
        dmcCsunGatewayCmdHi.setSensorNo(sensorNo);
        dmcCsunGatewayCmdHiMapper.sendOk(dmcCsunGatewayCmdHi);

    }

    private void dealGatewayHumidistatSetTimeAckMsg(String msg) {

        MsgHumidistatTimerAck msgHumidistatTimerAck = gson.fromJson(msg, MsgHumidistatTimerAck.class);
        //查询绑定房间
//        DmcCsunHumidistatLocation dmcCsunHumidistatLocation =
//                dmcCsunHumidistatLocationService.selectByKey(Long.valueOf(msgHumidistatTimerAck.getHumidistatId()));
//        if(dmcCsunHumidistatLocation == null){
//            throw new DmcBizException(ErrorCodeEnum.DMC100615001);
//        }

        dealGatewayMsgOk(MqttMsgConstants.GATEWAY_HUMIDISTAT_SET_TIME_MSG, msgHumidistatTimerAck.getEventId(),
                msgHumidistatTimerAck.getHumidistatId());


        String redisKey = RedisKeyUtil.getCsunGatewayKey(msgHumidistatTimerAck.getNetgateId());
        CsunGatewayData csunGatewayData = (CsunGatewayData) redisTemplate.opsForValue().get(redisKey);
        if (PublicUtil.isNotEmpty(csunGatewayData)) {
            DmcDevice dmcDevice = dmcDeviceService.queryDeviceByNumber(msgHumidistatTimerAck.getHumidistatId());
            if (PublicUtil.isEmpty(dmcDevice)) {
                return;
            }

            // 网关 - 温湿度计下发成功
            DmcCsunGatewayConfigHumidistat dmcCsunGatewayConfigHumidistat = new DmcCsunGatewayConfigHumidistat();
            dmcCsunGatewayConfigHumidistat.setGatewayId(csunGatewayData.getDeviceId());
            dmcCsunGatewayConfigHumidistat.setDeviceId(dmcDevice.getId());
            //dmcCsunGatewayConfigHumidistat.setDuration(Integer.parseInt(msgHumidistatTimerAck.getDuration()));
            //dmcCsunGatewayConfigHumidistat.setIsSend(1);
            dmcCsunGatewayConfigHumidistat = dmcCsunGatewayConfigHumidistatService.selectOne(dmcCsunGatewayConfigHumidistat);
            if (PublicUtil.isNotEmpty(dmcCsunGatewayConfigHumidistatService)) {
                dmcCsunGatewayConfigHumidistat.setIsSend(1);
                dmcCsunGatewayConfigHumidistat.setDuration(Integer.parseInt(msgHumidistatTimerAck.getDuration()));
                dmcCsunGatewayConfigHumidistatService.update(dmcCsunGatewayConfigHumidistat);
            }
        }

        //查询房间配置
//        DmcLifeTransducerConfig configQuery = new DmcLifeTransducerConfig();
//        configQuery.setLifeRoomId(dmcCsunHumidistatLocation.getRoomId().longValue());
//        configQuery = dmcLifeTransducerConfigService.selectOne(configQuery);
//
//        if(!configQuery.getTemperatureMeasuringTimeInterval().equals(msgHumidistatTimerAck.getDuration())){
//            gatewayMessageSender.humidistatTimer(msgHumidistatTimerAck.getNetgateId(),msgHumidistatTimerAck.getHumidistatId(),configQuery.getTemperatureMeasuringTimeInterval().toString());
//        }
    }

    /**
     * 处理网关 -- 温湿度消息
     *
     * @param msg
     */
    private void dealGatewayHumidistatMsg(String msg){


        MsgGatewayHumidistat msgGatewayHumidistat = gson.fromJson(msg, MsgGatewayHumidistat.class);

        String sn = msgGatewayHumidistat.getNetgateId();
        String redisKey = RedisKeyUtil.getCsunGatewayKey(sn);

        CsunGatewayData csunGatewayData = (CsunGatewayData) redisTemplate.opsForValue()
                .get(redisKey);

        if (PublicUtil.isNotEmpty(csunGatewayData)) {


            /**
             * 设置在线过期时间
             */
            refreshGatewayOnline(csunGatewayData);

            /*
             * 设置温度计过期时间
             * */
            refreshHumidistatOnline(msgGatewayHumidistat.getHumidistatId());

            /**
             * 判断是否为重复信息消息
             */
            if (checkGatewayMessage(MqttMsgConstants.GATEWAY_HUMIDISTAT_MSG, msgGatewayHumidistat)) {
                log.error("重复消息 msg ==> {}", msg);
            }

            // 数据更新
            if (updateHumidistat(csunGatewayData, msgGatewayHumidistat)) {
                // 数据保存
                saveHumidistat(csunGatewayData, msgGatewayHumidistat);
            }

        } else {
            log.error("csun gateway [{}] not load... ", sn);
        }

    }

    private void refreshHumidistatOnline(String humidistatId) {


        DmcDevice dmcDevice = dmcDeviceService.queryDeviceByNumber(humidistatId);

        String redisKey = RedisKeyUtil.getCsunHumidistatOnline(dmcDevice.getDeviceNo());
        DmcCsunHumidistatConfig dmcCsunHumidistatConfig = dmcCsunHumidistatConfigService.queryConfigByDeviceId(dmcDevice.getId());

        /**
         * @date    2020-03-26
         * @author  chisj
         * @desc    温湿度计绑定房间后才上线
         */
        if (PublicUtil.isEmpty(dmcDevice)) {
            log.warn("====> the humidistat [{}] not exist.", humidistatId);
            return;
        }
        DmcCsunHumidistatLocation record = dmcCsunHumidistatLocationService.selectByKey(dmcDevice.getId());
        if (PublicUtil.isEmpty(record)) {
            log.warn("====> the humidistat [{}] not bind.", record);
            return;
        }

        /**
         * @data    2020-03-19
         * @author  chisj
         * @desc    修复温湿度传感器频繁在线
         */
        String deviceNoQuery = (String) redisTemplate.opsForValue().get(redisKey);
        if (PublicUtil.isEmpty(deviceNoQuery)) {    // 温湿度计已经离线
            dmcDeviceOnlineRecordService.insertRecordByDeviceNo(dmcDevice.getDeviceNo(), OnlineConstant.ON_LINE);
            log.info("=====> chisj {} is empty", redisKey);
        } else {
            log.info("=====> chisj {} not empty", redisKey);
        }

        //修复如果温度计没有设置过期时间就无法写入在线状态的问题
        int expireTime=500;
        if (PublicUtil.isNotEmpty(dmcCsunHumidistatConfig)){
             expireTime = dmcCsunHumidistatConfig.getTemperatureMeasuringTimeInterval() * 2;
        }else {
            DmcLifeTransducerDefaultConfig dmcLifeTransducerDefaultConfig = lifeTransducerDefaultConfigService.selectByKey(dmcDevice.getGroupId());
            if (PublicUtil.isNotEmpty(dmcLifeTransducerDefaultConfig)){
                expireTime=dmcLifeTransducerDefaultConfig.getTemperatureMeasuringTimeInterval();
            }

        }

        /**
         * @author  chisj
         * @date    2020-11-19
         * @desc    固定300秒
         */
        expireTime = 300;
        redisTemplate.opsForValue().set(redisKey, humidistatId, expireTime, TimeUnit.SECONDS);

        if (!SleepMessageHandler.expireRedisKeySet.contains(redisKey))
            SleepMessageHandler.expireRedisKeySet.add(redisKey);
    }

    public void saveHumidistat(CsunGatewayData csunGatewayData, MsgGatewayHumidistat msgGatewayHumidistat) {



        String deviceNo = msgGatewayHumidistat.getHumidistatId();

        // 根据设备编号获取人感信息
        DmcDevice dmcDevice = dmcDeviceService.queryDeviceByNumber(deviceNo);
        if (PublicUtil.isEmpty(dmcDevice)) {
            log.error("设备不存在 deviceNo = {}", deviceNo);
            return;
        }

        DmcCsunHumidistatDataHi dmcCsunHumidistatDataHi = new DmcCsunHumidistatDataHi();
        dmcCsunHumidistatDataHi.setDeviceId(dmcDevice.getId());
        dmcCsunHumidistatDataHi.setHumidity(msgGatewayHumidistat.getHumidity());
        dmcCsunHumidistatDataHi.setTemperature(msgGatewayHumidistat.getTemperature());

        int temperature = Integer.parseInt(msgGatewayHumidistat.getTemperature());
        // 校验阈值设置范围
//        DmcCsunHumidistatThreshold dmcCsunHumidistatThreshold = dmcCsunHumidistatThresholdService
//                .selectByKey(dmcDevice.getId());
        /**
         * @date 2020-01-10
         * @author chisj
         * @desc 获取温湿度计阈值
         *          1）从温湿度计阈值设置中获取
         *          2）若绑定life房间，从房间配置中获取
         *          3）从系统配置中获取
         */
        DmcCsunHumidistatThreshold dmcCsunHumidistatThreshold = dmcCsunHumidistatThresholdService
                .queryThresholdByDeviceId(dmcDevice.getId());

        if (PublicUtil.isNotEmpty(dmcCsunHumidistatThreshold)) {
            if (temperature < dmcCsunHumidistatThreshold.getTemperatureMinimum()
                    || temperature > dmcCsunHumidistatThreshold.getTemperatureMaximum()) {
                // 温度值比最小值还小 或者 温度值比最大值还大 温度异常




                DmcDeviceAlert dmcDeviceAlert = new DmcDeviceAlert();
                OldmanBedRoomBuildingVo obrvo = new OldmanBedRoomBuildingVo();
                Integer result = dmcDeviceAlertService.csunHumidistatAlertMsg(msgGatewayHumidistat.getHumidistatId(), dmcDeviceAlert, obrvo, HumidistatConstant.CSUN_TEMPERATURE_ANOMAL);


                if (result > 0) {
                    dmcDeviceAlertService.sendDeviceAlertMsg(dmcDeviceAlert, obrvo);
                    dmcDeviceAlertService.sendLifeMsg(dmcDeviceAlert, obrvo, LifeConstant.YES_SOUND);
                }
            }
        }

        dmcCsunHumidistatDataHiService.save(dmcCsunHumidistatDataHi);
    }

    public boolean updateHumidistat(CsunGatewayData csunGatewayData, MsgGatewayHumidistat msgGatewayHumidistat) {

        String deviceNo = msgGatewayHumidistat.getHumidistatId();

        // 根据设备编号获取人感信息
        DmcDevice dmcDevice = dmcDeviceService.queryDeviceByNumber(deviceNo);
        if (PublicUtil.isEmpty(dmcDevice)) {
            log.error("设备不存在 deviceNo = {}", deviceNo);
            return false;
        }

        /**
         * @date 2020-03-03
         * @author chisj
         * @desc 没有绑定房间的温湿度计不保存数据
         */
        // 判断温湿度计是否有绑定房间
        DmcCsunHumidistatLocation dmcCsunHumidistatLocation = dmcCsunHumidistatLocationService.selectByKey(dmcDevice.getId());
        if (PublicUtil.isEmpty(dmcCsunHumidistatLocation)) {
            log.error("====> 温湿度计 [{}}] 未绑定房间", deviceNo);
            return false;
        }

        /**
         * @date 2020-03-03
         * @author chisj
         * @desc 没有绑定网关的温湿度计不保存数据
         */
        // 判断温湿度计是否有绑定网关
        DmcCsunGatewayBind dmcCsunGatewayBind = new DmcCsunGatewayBind();
        int count = dmcCsunGatewayBindService.selectCount(dmcCsunGatewayBind);
        if (count < 1) {
            log.error("====> 温湿度计 [{}}] 未绑定网关", deviceNo);
            return false;
        }

        DmcCsunHumidistatData dmcCsunHumidistatData = new DmcCsunHumidistatData();
        dmcCsunHumidistatData.setDeviceId(dmcDevice.getId());
        dmcCsunHumidistatData.setHumidity(msgGatewayHumidistat.getHumidity());
        dmcCsunHumidistatData.setTemperature(msgGatewayHumidistat.getTemperature());

        dmcCsunHumidistatDataService.saveOrUpdate(dmcCsunHumidistatData);

        return true;
    }


    /**
     * 处理网关 -- 人感电量消息
     *
     * @param msg
     */
    private void dealGatewayBodySensorAdcMsg(String msg) {

        MsgGatewayBodyAdc msgGatewayBodyAdc = gson.fromJson(msg, MsgGatewayBodyAdc.class);
        String sn = msgGatewayBodyAdc.getNetgateId();
        String redisKey = RedisKeyUtil.getCsunGatewayKey(sn);

        CsunGatewayData csunGatewayData = (CsunGatewayData) redisTemplate.opsForValue()
                .get(redisKey);

        if (PublicUtil.isNotEmpty(csunGatewayData)) {

            // 更新电量
            updateBodySensorAdc(msgGatewayBodyAdc);

            /**
             * 设置在线过期时间
             */
            refreshGatewayOnline(csunGatewayData);

            /**
             * 判断是否为重复信息消息
             */
            if (checkGatewayMessage(MqttMsgConstants.GATEWAY_BODY_ADC_MSG, msgGatewayBodyAdc)) {
                log.error("重复消息 msg ==> {}", msg);
            }

            DmcGatewayDataHi dmcGatewayDataHi = new DmcGatewayDataHi();
            dmcGatewayDataHi.setMsgType(MqttMsgConstants.GATEWAY_BODY_ADC_MSG);
            dmcGatewayDataHi.setDeviceId(csunGatewayData.getDeviceId());
            dmcGatewayDataHi.setStatus(csunGatewayData.getStatus());
            dmcGatewayDataHi.setNetgateNo(sn);
            dmcGatewayDataHi.setSensorNo(msgGatewayBodyAdc.getBodySensorId());
            dmcGatewayDataHiService.save(dmcGatewayDataHi);

            DmcGatewayData dmcGatewayData = new DmcGatewayData();
            dmcGatewayData.setMsgType(MqttMsgConstants.GATEWAY_BODY_ADC_MSG);
            dmcGatewayData.setDeviceId(csunGatewayData.getDeviceId());
            dmcGatewayData.setStatus(csunGatewayData.getStatus());
            dmcGatewayData.setNetgateNo(sn);
            dmcGatewayData.setSensorNo(msgGatewayBodyAdc.getBodySensorId());
            dmcGatewayDataService.saveOrUpdate(dmcGatewayData);

        } else {
            log.error("csun gateway [{}] not load... ", sn);
        }

    }

    private void updateBodySensorAdc(MsgGatewayBodyAdc msgGatewayBodyAdc) {

        String deviceNo = msgGatewayBodyAdc.getBodySensorId();
        String adcValue = msgGatewayBodyAdc.getAdcValue();

        String adcPercent = "0%";
        // 根据设备编号获取人感信息
        DmcDevice dmcDevice = dmcDeviceService.queryDeviceByNumber(deviceNo);

        try {
            Integer adc_int = Integer.parseInt(adcValue);

            if (adc_int.compareTo(18) <= 0) {
                adcPercent = "10%";
            } else {
                /**
                 * 计算电量（百分比）
                 */
                Double adc = (Float.valueOf(adcValue) * 0.06 - 1.07) * 100;
                adcPercent = String.format("%.0f%s", adc, "%");
            }

            if (PublicUtil.isEmpty(dmcDevice)) {
                log.error("设备不存在 deviceNo = {}", deviceNo);

                return;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("====> 电量计算失败");

            return;
        }

        DmcCsunBodySensorLocation dmcCsunBodySensorLocation = new DmcCsunBodySensorLocation();
        dmcCsunBodySensorLocation.setDeviceId(dmcDevice.getId());
        dmcCsunBodySensorLocation.setAdcValue(adcValue);
        dmcCsunBodySensorLocation.setAdcPercent(adcPercent);

        dmcCsunBodySensorLocationService.update(dmcCsunBodySensorLocation);
    }

    /**
     * 校验网关消息是否重复
     *
     * @param msgType
     * @param object
     * @return
     */
    private boolean checkGatewayMessage(String msgType, Object object) {

        String eventId = DateUtil.getDateStr(new Date());
        String redisKey = "";
        Object data;
        switch (msgType) {
            case MqttMsgConstants.GATEWAY_BODY_ADC_MSG:
                MsgGatewayBodyAdc msgGatewayBodyAdc = (MsgGatewayBodyAdc) object;
                if (PublicUtil.isNotEmpty(msgGatewayBodyAdc.getEventId())) {
                    eventId = msgGatewayBodyAdc.getEventId();
                }
                redisKey = RedisKeyUtil.getCsunGatewayBodyAdc(msgGatewayBodyAdc.getBodySensorId(), eventId);
                break;
            case MqttMsgConstants.GATAWAY_BTN_MSG:
                MsgGatewayButton msgGatewayButton = (MsgGatewayButton) object;
                if (PublicUtil.isNotEmpty(msgGatewayButton.getEventId())) {
                    eventId = msgGatewayButton.getEventId();
                } else {
                    msgGatewayButton.setEventId(eventId);
                }
                redisKey = RedisKeyUtil.getCsunGatewayButton(msgGatewayButton.getButtonId(), eventId);
                break;
            case MqttMsgConstants.GATEWAY_BODY_MSG:
                MsgGatewayBodySensor msgGatewayBodySensor = (MsgGatewayBodySensor) object;
                if (PublicUtil.isNotEmpty(msgGatewayBodySensor.getEventId())) {
                    eventId = msgGatewayBodySensor.getEventId();
                } else {
                    msgGatewayBodySensor.setEventId(eventId);
                }
                redisKey = RedisKeyUtil.getCsunGatewayBodySensor(msgGatewayBodySensor.getBodySensorId(), eventId);
                break;
            case MqttMsgConstants.INVITE_HEAT:
                MsgInviteHeat msgInviteHeat = (MsgInviteHeat) object;
                if (PublicUtil.isNotEmpty(msgInviteHeat.getEventId())) {
                    eventId = msgInviteHeat.getEventId();
                } else {
                    msgInviteHeat.setEventId(eventId);
                }
                redisKey = RedisKeyUtil.getCsunGateway(msgInviteHeat.getSn(), eventId);
                break;
            case MqttMsgConstants.GATEWAY_BODY_SENSOR_TOUCH :
                MsgBodyTouchMsg msgBodyTouchMsg = (MsgBodyTouchMsg) object;
                if (PublicUtil.isNotEmpty(msgBodyTouchMsg.getEventId())) {
                    eventId = msgBodyTouchMsg.getEventId();
                } else {
                    msgBodyTouchMsg.setEventId(eventId);
                }
                redisKey = RedisKeyUtil.getCsunGateway(msgBodyTouchMsg.getNetgateId(), eventId);
                break;
            default:
                log.error("未识别的消息 ==> {}", msgType);
                break;
        }
        log.info("==> redis key = {}", redisKey);
//        data = redisTemplate.opsForValue().get(redisKey);
//        if (PublicUtil.isNotEmpty(data)) {
//            return true;    // 重复性消息
//        }
//
        if (redisTemplate.hasKey(redisKey)) {
            return true;    // 重复性消息
        }
//        // 设置有效期
        redisTemplate.opsForValue().set(redisKey, object.toString(), RedisKeyUtil.getMsgExpire(), TimeUnit.SECONDS);
//
        return false;
//      // true - 创建redis失败 - 已经存在key
        // false - 创建redis成功 - 不存在key
//        return getLock(redisKey, object.toString(), 600);
    }

    /**
     * 处理网关--心跳消息
     *
     * @param msg
     */
    private void dealGatewayHeat(String msg) {

        MsgInviteHeat msgInviteHeat = gson.fromJson(msg, MsgInviteHeat.class);
        String sn = msgInviteHeat.getSn();
        String redisKey = RedisKeyUtil.getCsunGatewayKey(sn);

        CsunGatewayData csunGatewayData = (CsunGatewayData) redisTemplate.opsForValue().get(redisKey);



        if (PublicUtil.isNotEmpty(csunGatewayData)) {

            /**
             * 设置在线过期时间
             */
            refreshGatewayOnline(csunGatewayData);

            /**
             * 判断是否为重复信息消息
             */
//            if (checkGatewayMessage(MqttMsgConstants.INVITE_HEAT, msgInviteHeat)) {
//                log.error("重复消息 msg ==> {}", msg);
//            }

            // 发送网关离线命令
            sendGatewayOffCmd(csunGatewayData);

            /**
             * @date    2020-04-01
             * @author  chisj
             * @desc    更新设备版本号
             */
            if (PublicUtil.isNotEmpty(msgInviteHeat.getVersion())) {
                updateDeviceVersion(msgInviteHeat.getVersion(), csunGatewayData);
            }

            redisTemplate.opsForValue().set(redisKey, csunGatewayData);
        } else {
            log.error("csun gateway [{}] not load... ", sn);
        }

    }

    /**
     * 更新设备状态
     *
     * @param version           the device version
     * @param csunGatewayData   the csun gateway data
     */
    private void updateDeviceVersion(String version, CsunGatewayData csunGatewayData) {

        if (PublicUtil.isEmpty(version)) {
            return;
        }

        if (!version.equals(csunGatewayData.getDeviceVersion())) {

            dmcDeviceService.updateDeviceVersion(csunGatewayData.getDeviceId(), version);

            // 版本替换
            csunGatewayData.setDeviceVersion(version);
        }
    }

    /**
     * 下发离线指令
     *
     * @param csunGatewayData
     */
    private void sendGatewayOffCmd(CsunGatewayData csunGatewayData) {

        DmcCsunGatewayCmd dmcCsunGatewayCmd = new DmcCsunGatewayCmd();
        dmcCsunGatewayCmd.setDeviceId(csunGatewayData.getDeviceId());
        dmcCsunGatewayCmd.setDeviceNo(csunGatewayData.getDeviceNo());
        List<DmcCsunGatewayCmd> dmcCsunGatewayCmdList = dmcCsunGatewayCmdMapper.select(dmcCsunGatewayCmd);
        if (PublicUtil.isEmpty(dmcCsunGatewayCmdList)) {
            return;
        }

        for (DmcCsunGatewayCmd cmd : dmcCsunGatewayCmdList) {
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            }

            csunGatewayMessageGateway.sendToMqtt(cmd.getDeviceNo(), cmd.getQos(), cmd.getContent());
        }

    }

    /**
     * 处理网关--离线消息
     *
     * @param msg
     */
    private void dealGatewayClose(String msg) {

        MsgInviteClose msgInviteClose = gson.fromJson(msg, MsgInviteClose.class);
        String sn = msgInviteClose.getSn();
        String redisKey = RedisKeyUtil.getCsunGatewayKey(sn);

        CsunGatewayData csunGatewayData = (CsunGatewayData) redisTemplate.opsForValue()
                .get(redisKey);

        if (PublicUtil.isNotEmpty(csunGatewayData)) {
            /*
             * 2020-03-18 xcr
             * 由于连续收到网关离线消息 改为仅通过redis失效key判定网关离线
             * */
//            if (!csunGatewayData.getStatus().equals(DeviceStatusEnum.OFFLINE.getKey())) {
//                csunGatewayData.setStatus(DeviceStatusEnum.OFFLINE.getKey());
//
//                redisTemplate.opsForValue().set(redisKey, csunGatewayData);
//
//                DmcGatewayDataHi dmcGatewayDataHi = new DmcGatewayDataHi();
//                dmcGatewayDataHi.setMsgType(MqttMsgConstants.INVITE_CLOSE);
//                dmcGatewayDataHi.setDeviceId(csunGatewayData.getDeviceId());
//                dmcGatewayDataHi.setStatus(csunGatewayData.getStatus());
//                dmcGatewayDataHi.setNetgateNo(sn);
//                dmcGatewayDataHiService.save(dmcGatewayDataHi);
//
//                DmcGatewayData dmcGatewayData = new DmcGatewayData();
//                dmcGatewayData.setMsgType(MqttMsgConstants.INVITE_CLOSE);
//                dmcGatewayData.setDeviceId(csunGatewayData.getDeviceId());
//                dmcGatewayData.setStatus(csunGatewayData.getStatus());
//                dmcGatewayData.setNetgateNo(sn);
//                dmcGatewayDataService.saveOrUpdate(dmcGatewayData);
//
//                /*
//                 * 2020-03-18
//                 * 网关离线
//                 * */
//                dmcDeviceAlertService.deviceOfflineAlert(sn);
//            }
        } else {
            log.error("csun gateway [{}] not load... ", sn);
        }
    }

    /**
     * 处理网关 - 门锁消息
     *
     * @param msg
     */
    private void dealDoorMsg(String msg) {

        MsgDoor msgDoor = gson.fromJson(msg, MsgDoor.class);
        String sn = msgDoor.getNetgateId();
        String redisKey = RedisKeyUtil.getCsunGatewayKey(sn);

        CsunGatewayData csunGatewayData = (CsunGatewayData) redisTemplate.opsForValue()
                .get(redisKey);

        if (PublicUtil.isNotEmpty(csunGatewayData)) {

            /**
             * 设置在线过期时间
             */
//            refreshGatewayOnline(csunGatewayData);

            /**
             * 判断是否为重复信息消息
             */
//            if (checkGatewayMessage(MqttMsgConstants.GATAWAY_BTN_MSG, msgDoor)) {
//                log.error("重复消息 msg ==> {}", msg);
//                return;
//            }

            DmcGatewayDataHi dmcGatewayDataHi = new DmcGatewayDataHi();
            dmcGatewayDataHi.setMsgType(MqttMsgConstants.GATAWAY_BTN_MSG);
            dmcGatewayDataHi.setDeviceId(csunGatewayData.getDeviceId());
            dmcGatewayDataHi.setStatus(csunGatewayData.getStatus());
            dmcGatewayDataHi.setNetgateNo(sn);
            dmcGatewayDataHi.setSensorNo(msgDoor.getDoorId());
            dmcGatewayDataHiService.save(dmcGatewayDataHi);

            DmcGatewayData dmcGatewayData = new DmcGatewayData();
            dmcGatewayData.setMsgType(MqttMsgConstants.GATAWAY_BTN_MSG);
            dmcGatewayData.setDeviceId(csunGatewayData.getDeviceId());
            dmcGatewayData.setStatus(csunGatewayData.getStatus());
            dmcGatewayData.setNetgateNo(sn);
            dmcGatewayData.setSensorNo(msgDoor.getDoorId());
            dmcGatewayDataService.saveOrUpdate(dmcGatewayData);

            DmcDeviceAlert dmcDeviceAlert = new DmcDeviceAlert();
            OldmanBedRoomBuildingVo obrvo = new OldmanBedRoomBuildingVo();
            Integer result = dmcDeviceAlertService.csunDoorAlertMsg(msgDoor.getDoorId(), dmcDeviceAlert, obrvo);
            if (result > 0) {
                dmcDeviceAlertService.sendDeviceAlertMsg(dmcDeviceAlert, obrvo);
                dmcDeviceAlertService.sendLifeMsg(dmcDeviceAlert, obrvo, LifeConstant.YES_SOUND);
            }
        } else {
            log.error("csun gateway [{}] not load... ", sn);
        }
    }

    /**
     * 处理网关--紧急按钮消息
     *
     * @param msg
     */
    private void dealGatewayButtonMsg(String msg) {
        MsgGatewayButton msgGatewayButton = gson.fromJson(msg, MsgGatewayButton.class);
        String sn = msgGatewayButton.getNetgateId();
        /**
         * @date    2021-11-22
         * @author  chisj
         * @desc    线上运行存在故障
         */

        DeviceAlertPageQuery deviceAlertPageQuery = new DeviceAlertPageQuery();
        deviceAlertPageQuery.setDeviceNo(msgGatewayButton.getButtonId());
        //查询该设备最新报警时间
        List<DmcDeviceAlertVo> deviceAlertVos = dmcDeviceAlertService.queryDeviceAlert(deviceAlertPageQuery);
        //查询该设备报警时间间隔
        CsunButtonPageQuery csunButtonPageQuery = new CsunButtonPageQuery();
        csunButtonPageQuery.setDeviceId(deviceAlertVos.get(0).getDeviceId());
        DmcCsunButtonVo dmcCsunButtonVo = dmcCsunButtonLocationServiceImpl.queryGroupCsunButton(csunButtonPageQuery);
        //判断报警时间是否在时间间隔内
        long currentTime = System.currentTimeMillis();
        if(deviceAlertVos != null && deviceAlertVos.size() > 0){
            long createdTime = deviceAlertVos.get(0).getCreatedTime().getTime();
            if(dmcCsunButtonVo.getAlarmTime() == null){
                dmcCsunButtonVo.setAlarmTime(0);
            }
            if(currentTime < (createdTime + dmcCsunButtonVo.getAlarmTime()*60*1000)){
                return;
            }
        }

        String redisKey = RedisKeyUtil.getCsunGatewayKey(sn);
        CsunGatewayData csunGatewayData = (CsunGatewayData) redisTemplate.opsForValue()
                .get(redisKey);

//        CsunGatewayData tmp = new CsunGatewayData();
//        tmp.setDeviceId(1l);
//        tmp.setStatus("online");
//        tmp.setDeviceNo(sn);
//        // 测试 == 离线设置
//        redisTemplate.opsForValue().set(RedisKeyUtil.getCsunGatewayOnline(sn),
//                tmp, 60, TimeUnit.SECONDS);

        if (PublicUtil.isNotEmpty(csunGatewayData)) {

            /**
             * 设置在线过期时间
             */
            refreshGatewayOnline(csunGatewayData);

            /**
             * 判断是否为重复信息消息
             */
            if (checkGatewayMessage(MqttMsgConstants.GATAWAY_BTN_MSG, msgGatewayButton)) {
                log.error("重复消息 msg ==> {}", msg);
                return;
            }

            DmcGatewayDataHi dmcGatewayDataHi = new DmcGatewayDataHi();
            dmcGatewayDataHi.setMsgType(MqttMsgConstants.GATAWAY_BTN_MSG);
            dmcGatewayDataHi.setDeviceId(csunGatewayData.getDeviceId());
            dmcGatewayDataHi.setStatus(csunGatewayData.getStatus());
            dmcGatewayDataHi.setNetgateNo(sn);
            dmcGatewayDataHi.setSensorNo(msgGatewayButton.getButtonId());
            dmcGatewayDataHiService.save(dmcGatewayDataHi);

            DmcGatewayData dmcGatewayData = new DmcGatewayData();
            dmcGatewayData.setMsgType(MqttMsgConstants.GATAWAY_BTN_MSG);
            dmcGatewayData.setDeviceId(csunGatewayData.getDeviceId());
            dmcGatewayData.setStatus(csunGatewayData.getStatus());
            dmcGatewayData.setNetgateNo(sn);
            dmcGatewayData.setSensorNo(msgGatewayButton.getButtonId());
            dmcGatewayDataService.saveOrUpdate(dmcGatewayData);

            DmcDeviceAlert dmcDeviceAlert = new DmcDeviceAlert();
            OldmanBedRoomBuildingVo obrvo = new OldmanBedRoomBuildingVo();
            dmcDeviceAlert.setEventId(msgGatewayButton.getEventId());
            Integer result = dmcDeviceAlertService.csunButtonAlertMsg(msgGatewayButton.getButtonId(), dmcDeviceAlert, obrvo);
            if (result > 0) {
                dmcDeviceAlertService.sendDeviceAlertMsg(dmcDeviceAlert, obrvo);
                dmcDeviceAlertService.sendLifeMsg(dmcDeviceAlert, obrvo, LifeConstant.YES_SOUND);
            }
        } else {
            log.error("csun gateway [{}] not load... ", sn);
        }

    }

    private void refreshGatewayOnline(CsunGatewayData csunGatewayData) {

        String deviceNo = csunGatewayData.getDeviceNo();

        /**
         * @desc    2020-03-19
         * @author  chisj
         * @desc    修复网关频繁在线记录
         */
        if (DeviceStatusEnum.OFFLINE.getKey().equals(csunGatewayData.getStatus())) {    // 判断网关离线
            dmcDeviceOnlineRecordService.insertRecordByDeviceNo(deviceNo, OnlineConstant.ON_LINE);

            // 更新网关在线
            csunGatewayData.setStatus(DeviceStatusEnum.ONLINE.getKey());
            // 刷新redis
            redisTemplate.opsForValue().set(RedisKeyUtil.getCsunGatewayKey(deviceNo), csunGatewayData);
        }

        redisTemplate.opsForValue().set(RedisKeyUtil.getCsunGatewayOnline(deviceNo),
                csunGatewayData, DeviceConstant.DEVICE_GATEWAY_ONLINE_EXPIRE, TimeUnit.SECONDS);

        /*
         * 2020-03-12 xcr
         * 判断上传心跳的网关是否已经缓存，没有则缓存
         * */
        if (!SleepMessageHandler.expireRedisKeySet.contains(RedisKeyUtil.getCsunGatewayOnline(deviceNo)))
            SleepMessageHandler.expireRedisKeySet.add(RedisKeyUtil.getCsunGatewayOnline(deviceNo));

    }

    @Test
    public void fromJson() {

        String json = "{\"msgType\":\"bodySensorMsg\",\"netgateId\":\"10013\",\"bodySensorId\":\"10000010\"}";
        // String json = "{\"msgType\":\"bodySensorMsg\",\"netgateId\":\"10013\",\"eventId\":\"1573785423\",\"bodySensorId\":\"10000010\"}";

        MsgGatewayBodySensor msgGatewayBodySensor = gson.fromJson(json, MsgGatewayBodySensor.class);

        System.out.println("msgGatewayBodySensor = " + msgGatewayBodySensor);
    }

    /**
     * 处理网关--人体感应触发消息
     *
     * @param msg
     */
    private void dealGatewayBodyTouchMsg(String msg) {

        MsgBodyTouchMsg msgBodyTouchMsg = gson.fromJson(msg, MsgBodyTouchMsg.class);
        String sn = msgBodyTouchMsg.getNetgateId();
        String redisKey = RedisKeyUtil.getCsunGatewayKey(sn);

        CsunGatewayData csunGatewayData = (CsunGatewayData) redisTemplate.opsForValue()
                .get(redisKey);

        if (PublicUtil.isNotEmpty(csunGatewayData)) {

            /**
             * 设置在线过期时间
             */
            refreshGatewayOnline(csunGatewayData);

            /**
             * 判断是否为重复信息消息
             */
            if (checkGatewayMessage(MqttMsgConstants.GATEWAY_BODY_SENSOR_TOUCH, msgBodyTouchMsg)) {
                log.error("重复消息 msg ==> {}", msg);
            }

            // 重置人感组持续时间
            BodyGroupVo bodyGroupVo = dmcCsunBodyGroupBindService
                    .queryBodyGroupByDeviceNo(msgBodyTouchMsg.getBodySensorId());
            if (PublicUtil.isEmpty(bodyGroupVo)) {
                log.error("body touch msg body group not load... {}", msgBodyTouchMsg.getBodySensorId());
                return ;
            }


            DmcDevice dmcDevice = dmcDeviceService.queryDeviceByNumber(msgBodyTouchMsg.getBodySensorId());
            if (PublicUtil.isNotEmpty(dmcDevice)) {
                DmcCsunBodyGroup dmcCsunBodyGroup = dmcCsunBodyGroupService.selectByKey(bodyGroupVo.getId());
                if (PublicUtil.isNotEmpty(dmcCsunBodyGroup)) {
                    dmcCsunBodyGroup.setDeviceId(dmcDevice.getId());
                    dmcCsunBodyGroup.setDeviceNo(dmcDevice.getDeviceNo());
                    dmcCsunBodyGroup.setTouchDate(new Date());

                    dmcCsunBodyGroupService.update(dmcCsunBodyGroup);
                }
            }

            bodyGroupVo.setTouch(1);
            bodyGroupVo.setDeviceNo(msgBodyTouchMsg.getBodySensorId());
            bodyGroupVo.setTouchDate(DateUtil.getCurrentDate());

            // 设置人感持续时间
            String timeKey = RedisKeyUtil.getCsunBodyGroupKey(bodyGroupVo.getId());
            // 刷新key
            if (!SleepMessageHandler.expireRedisKeySet.contains(timeKey))
                SleepMessageHandler.expireRedisKeySet.add(timeKey);

            redisTemplate.opsForValue().set(timeKey, bodyGroupVo, bodyGroupVo.getTimeOut(), TimeUnit.MINUTES);

        } else {
            log.error("csun gateway [{}] not load... ", sn);
        }

    }

    /**
     * 处理网关--人体感应消息
     *
     * @param msg
     */
    private void dealGatewayBodySensorMsg(String msg) {

        MsgGatewayBodySensor msgGatewayBodySensor = gson.fromJson(msg, MsgGatewayBodySensor.class);
        String sn = msgGatewayBodySensor.getNetgateId();
        String redisKey = RedisKeyUtil.getCsunGatewayKey(sn);

        CsunGatewayData csunGatewayData = (CsunGatewayData) redisTemplate.opsForValue()
                .get(redisKey);

        if (PublicUtil.isNotEmpty(csunGatewayData)) {

            /**
             * 设置在线过期时间
             */
            refreshGatewayOnline(csunGatewayData);

            /**
             * 判断是否为重复信息消息
             */
            if (checkGatewayMessage(MqttMsgConstants.GATEWAY_BODY_MSG, msgGatewayBodySensor)) {
                log.error("重复消息 msg ==> {}", msg);
            }

            csunGatewayData.setStatus(DeviceStatusEnum.ONLINE.getKey());

            DmcGatewayDataHi dmcGatewayDataHi = new DmcGatewayDataHi();
            dmcGatewayDataHi.setMsgType(MqttMsgConstants.GATEWAY_BODY_MSG);
            dmcGatewayDataHi.setDeviceId(csunGatewayData.getDeviceId());
            dmcGatewayDataHi.setStatus(csunGatewayData.getStatus());
            dmcGatewayDataHi.setNetgateNo(sn);
            dmcGatewayDataHi.setSensorNo(msgGatewayBodySensor.getBodySensorId());
            dmcGatewayDataHiService.save(dmcGatewayDataHi);

            DmcGatewayData dmcGatewayData = new DmcGatewayData();
            dmcGatewayData.setMsgType(MqttMsgConstants.GATEWAY_BODY_MSG);
            dmcGatewayData.setDeviceId(csunGatewayData.getDeviceId());
            dmcGatewayData.setStatus(csunGatewayData.getStatus());
            dmcGatewayData.setNetgateNo(sn);
            dmcGatewayData.setSensorNo(msgGatewayBodySensor.getBodySensorId());
            dmcGatewayDataService.saveOrUpdate(dmcGatewayData);

            DmcDeviceAlert dmcDeviceAlert = new DmcDeviceAlert();
            OldmanBedRoomBuildingVo obrvo = new OldmanBedRoomBuildingVo();
            Integer result = dmcDeviceAlertService.csunBodySensorAlertMsg(msgGatewayBodySensor.getBodySensorId(), dmcDeviceAlert, obrvo, msgGatewayBodySensor.getLevel());
                if (result > 0) {
                    dmcDeviceAlertService.sendDeviceAlertMsg(dmcDeviceAlert, obrvo);
                    String sound = LifeConstant.YES_SOUND;
                    switch (msgGatewayBodySensor.getLevel()) {
                        case LifeConstant.BODY_SENSOR_TOILET_ATTENTION_LEVEL:
                            sound = LifeConstant.NO_SOUND;
                            break;
                        case LifeConstant.BODY_SENSOR_TOILET_WARNING_LEVEL:
                            sound = LifeConstant.NO_SOUND;
                            break;
                    }
                    dmcDeviceAlertService.sendLifeMsg(dmcDeviceAlert, obrvo, sound);
                }
        } else {
            log.error("csun gateway [{}] not load... ", sn);
        }

    }

    /**
     * 处理设备log信息
     *
     * @param msg
     */
    private void dealLogMsg(String msg) {

        MsgLog msgLog = gson.fromJson(msg, MsgLog.class);

        /**
         * @date    2020-05-20
         * @author  chisj
         * @desc    采集设备日志
         */
        deviceLogUtils.print(msgLog);

        String sn = msgLog.getSn();
        String redisKey = RedisKeyUtil.getCsunGatewayKey(sn);

        CsunGatewayData csunGatewayData = (CsunGatewayData) redisTemplate.opsForValue()
                .get(redisKey);

        if (PublicUtil.isNotEmpty(csunGatewayData)) {

            DmcDeviceLog dmcDeviceLog = new DmcDeviceLog();
            BeanUtils.copyProperties(msgLog, dmcDeviceLog);

            // 获取设备信息
            DmcDevice dmcDevice = dmcDeviceService.selectByKey(csunGatewayData.getDeviceId());

            if (PublicUtil.isEmpty(dmcDevice)) {
                log.error("csun gateway [{}] not exist... ", sn);
            }

            // 获取设备的位置
            dmcDeviceLog.setDeviceId(csunGatewayData.getDeviceId());
            dmcDeviceLog.setDeviceNo(csunGatewayData.getDeviceNo());
            dmcDeviceLog.setGroupId(dmcDevice.getGroupId());
            dmcDeviceLog.setDeviceName(dmcDevice.getDeviceName());

            // 存储日志
            dmcDeviceLogService.save(dmcDeviceLog);

        } else {
            log.error("csun gateway [{}] not load... ", sn);
        }
    }


    public boolean getLock(String lockKey, String value, int expireTime) {

        boolean ret = true;
        Long SUCCESS = 1L;

        try{
            String script = "if redis.call('setNx',KEYS[1],ARGV[1]) then if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('expire',KEYS[1],ARGV[2]) else return 0 end end";

            RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);

            Object result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey),value,expireTime);
            log.info("====> chisj result = " + result);
            if(SUCCESS.equals(result)) {
                return false;
            }
        } catch(Exception e){
            e.printStackTrace();
        }

        return ret;
    }


//    private void saveOnlineRecord(String Status, String deviceNo) {
//        // 设备从离线,变成在线
//        if (Status.equals(DeviceStatusEnum.OFFLINE.getKey())) {
//            //插入在线日志
//            Integer save = dmcDeviceOnlineRecordService.insertRecordByDeviceNo(deviceNo, OnlineConstant.ON_LINE);
//        }
//    }
}
